package com.itelite.service.impl;

import com.itelite.service.RedisService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.ListOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.Set;
import java.util.concurrent.TimeUnit;
@Slf4j
@Service
public class RedisServiceImpl implements RedisService {
    /**
     * slf4j 日志
     */


    /**
     * 自定义 key 三种
     *  String key:String value         普通key:value
     *  String key:Set<String> set      key:set集合
     *  String key:List<String> list    key:list集合
     */
    private static final String KEY_PREFIX_KEY = "itelite:info:key:";
    private static final String KEY_PREFIX_SET = "itelite:info:set:";
    private static final String KEY_PREFIX_LIST = "itelite:info:list:";

    @Autowired
    private RedisTemplate<String, Object> redisTemplate;



    /**
     * 添加 key:string 缓存
     *
     * @param k    key
     * @param v    value
     * @param time time
     */
    @Override
    public boolean cacheValue(String k, Object v, long time) {
        try {
            String key = KEY_PREFIX_KEY + k;
            ValueOperations<String, Object> ops = redisTemplate.opsForValue();
            ops.set(key, v);
            if (time > 0) {
                redisTemplate.expire(key, time, TimeUnit.SECONDS);
            }
            return true;
        } catch (Throwable e) {
            log.error("缓存存入失败key:[{}] value:[{}]", k, v);
        }
        return false;
    }



    /**
     * 添加 key:string 缓存
     *
     * @param key   key
     * @param value value
     */
    @Override
    public boolean cacheValue(String key, Object value) {
        return cacheValue(key, value, -1);
    }




    @Override
    public boolean containsKey(String key) {
        try {
            return redisTemplate.hasKey(key);
        } catch (Throwable e) {
            log.error("判断缓存存在失败key:[" + key + "],错误信息 Codeor[{}]", e);
        }
        return false;
    }



    /**
     * 根据 key 获取缓存value
     *
     * @param key key
     * @return value
     */
    @Override
    public Object getValue(String key) {
        try {
            ValueOperations<String, Object> ops = redisTemplate.opsForValue();
            return  ops.get(KEY_PREFIX_KEY + key);
        } catch (Throwable e) {
            log.error("根据 key 获取缓存失败，当前key:[{}],失败原因 Codeor:[{}]", key, e);
        }
        return null;
    }











    /**
     * 缓存 list 集合
     * @param k key
     * @param v value
     * @param time 时间
     */
    @Override
    public boolean cacheList(String k, List<?> v, long time) {
        try {
            String key = KEY_PREFIX_LIST + k;
            ListOperations<String, Object> opsForList = redisTemplate.opsForList();
            opsForList.leftPushAll(key,v);
            if (time > 0){
                redisTemplate.expire(key,time,TimeUnit.SECONDS);
            }
            return true;
        }catch (Throwable e){
            log.error("缓存list失败 当前 key:[{}],失败原因 [{}]", k, e);
        }
        return false;
    }


    /**
     *  缓存 list
     * @param k key
     * @param v value
     * @return true/false
     */
    @Override
    public boolean cacheList(String k, List<?> v) {
        return cacheList(k,v,-1);
    }


    /**
     * 根据 key 获取 list 缓存
     * @param k key
     * @param start 开始
     * @param end 结束
     * @return 获取缓存区间内 所有value
     */
    @Override
    public List<Object> getList(String k, long start, long end) {
        try {
            String key = KEY_PREFIX_LIST + k;
            ListOperations<String, Object> opsForList = redisTemplate.opsForList();
            return opsForList.range(key,start,end);
        }catch (Throwable e){
            log.error("获取list缓存失败 当前 key:[{}],失败原因 [{}]", k, e);
        }
        return null;
    }

    @Override
    public List<Object> getList(String k, long start, long end,long cacheSecond) {
        try {
            String key = KEY_PREFIX_LIST + k;
            ListOperations<String, Object> opsForList = redisTemplate.opsForList();
            if (cacheSecond > 0){
                redisTemplate.expire(key,cacheSecond,TimeUnit.SECONDS);
            }
            return opsForList.range(key,start,end);
        }catch (Throwable e){
            log.error("获取list缓存失败 当前 key:[{}],失败原因 [{}]", k, e);
        }
        return null;
    }



    /**
     * 根据 key 移除 list 缓存
     * @param k key
     */
    @Override
    public boolean removeOneOfList(String k) {
        try {
            String key = KEY_PREFIX_LIST + k;
            ListOperations<String, Object> opsForList = redisTemplate.opsForList();
            opsForList.rightPop(key);
            return true;
        }catch (Throwable e){
            log.error("移除list缓存失败 key[" + KEY_PREFIX_LIST + k + "], Codeor[" + e + "]");
        }
        return false;
    }

    @Override
    public void removeAllValue() {
        Set<String> keys = redisTemplate.keys("*");
        assert keys != null;
        for (String key : keys) {
            redisTemplate.delete(key);
        }
    }


    /**
     * 根据 key 移除 value 缓存
     *
     * @param key key
     * @return true/false
     */
    @Override
    public boolean removeValue(String key) {
        return remove(KEY_PREFIX_KEY + key);
    }




    /**
     * 根据 key 移除 list 缓存
     *
     * @param key key
     * @return true/false
     */
    @Override
    public boolean removeList(String key) {
        return remove(KEY_PREFIX_LIST + key);
    }

    /**
     * 移除缓存
     *
     * @param key key
     * @return boolean
     */
    private boolean remove(String key) {
        try {
            redisTemplate.delete(key);
            return true;
        } catch (Throwable e) {
            log.error("移除缓存失败 key:[{}] 失败原因 [{}]", key, e);
        }
        return false;
    }
}

